package ru.urfc.portal.ui.client;

import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.tips.Tip;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.GwtEvent.Type;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.RootPanel;

import ru.urfc.portal.ui.client.controllers.BaseController;
import ru.urfc.portal.ui.client.controllers.ErrorReporter;
import ru.urfc.portal.ui.client.controllers.GridController;
import ru.urfc.portal.ui.client.controllers.ItemsController;
import ru.urfc.portal.ui.client.descriptor.GridDescriptor;
import ru.urfc.portal.ui.client.descriptor.GridField;
import ru.urfc.portal.ui.portlets.BasePortlet;

import java.util.List;

public abstract class BaseGooglet extends Composite implements Constants {
	
	private App urfcApp;
	private String name;
	/**
	 * A widget already have handlerManager so property renamed as eventsDispatcher 
	 */
	private HandlerManager eventsDispatcher;
	
	protected void showInfoTip(String info) {
		final Tip tip = new Tip();
		tip.setHeaderVisible(false);
		tip.addText(info);
		final int screenWidth = RootPanel.get().getOffsetWidth();
		tip.showAt(screenWidth / 2 - 80, 120);
		Timer timer = new Timer() {
			@Override
			public void run() {
				tip.hide();
				tip.removeFromParent();
			}
		};
		timer.schedule(3000);
	}
	
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}
	
	public String getClientId() {
		return getProperty(GOOGLET_PARAMETER_CLIENT_ID);
	}
	
	protected String getUserId() {
		return getProperty(GOOGLET_PARAMETER_USER_ID);
	}
	
	public String getItemId() {
		return getPageParam("id");
	}
	
	protected String getDocumentType() {
		return getPageParam("type");
	}
	
	private String getPageParam(String paramName) {
		return Utils.extractPageParam(paramName, getPageParams());
	}

	native private String getPageParams() /*-{
		return $wnd.document.location.search.toString();
	}-*/;

	/**
	 * Read property rendered by {@link BasePortlet}
	 * @param name
	 * @return
	 */
	protected String getProperty(String name) {
		return getRootPanel().getElement().getAttribute(name);
	}

	private RootPanel getRootPanel() {
		return RootPanel.get(getName());
	}
	
	abstract protected void init();
	
	public void setEventsDispatcher(HandlerManager handlerManager) {
		this.eventsDispatcher = handlerManager;		
	}

	public HandlerManager getEventsDispatcher() {
		return eventsDispatcher;
	}
	
	public ItemsController createController(GridDescriptor descriptor) {
		return register(App.DO_UPDATE, new ItemsController(descriptor));
	}
	
	public ItemsController createController(GridDescriptor descriptor, Element parent, Element itemTemplate) {
		return register(App.DO_UPDATE, new ItemsController(descriptor, parent, itemTemplate));
	}

	//TODO make protected  
	public GridController createController(GridDescriptor descriptor, Grid<ModelData> grid) {
		return createController(descriptor, grid, null);
	}

	protected GridController createController(GridDescriptor descriptor, final Grid<ModelData> grid, PagingToolBar paging) {
		GridController controller = new GridController(descriptor);
		controller.setErrorReporter(new ErrorReporter() {
			@Override
			public void reportError(String message) {
				grid.mask("Ошибка загрузки данных");
			}
		});
		register(App.DO_UPDATE, controller);
		if (paging != null) {
			controller.setPaging(paging);
		}
		grid.reconfigure(controller.createStore(), descriptor.getColumnModel());
		return controller;
	}

	protected ListStore<ModelData> createStore(GridDescriptor descriptor, final ModelData modelDataAll) {
		GridController controller = new GridController(descriptor) {
			@Override
			protected void onLoad(List<ModelData> data) {
				if (modelDataAll != null) {
					data.add(0, modelDataAll);
				}
			}
		};
		register(App.DO_UPDATE, controller);
		return controller.createStore();
	}	
	
	//TODO make protected  
	public <T extends BaseController, S extends T> S register(Type<T> eventType, S controller) {
		if (isDevMode()) {
			controller.patchUrls(true, getPageParam(Constants.GWT_DEBUG_ARG));
		}
		eventsDispatcher.addHandler(eventType, controller);
		return controller;
	}
	
	protected boolean isDevMode() {
		return !GWT.isScript();
	}

	protected String patchHref(String url) {
		return isDevMode()? Utils.patchHref(url, getPageParam(Constants.GWT_DEBUG_ARG)): url;
	}
	
	native protected void createWindowForPrinting(String content) /*-{
		wnd = window.open("");
		doc = wnd.document;
		doc.open("text/html");
		doc.write(content);
		doc.close();
		wnd.print();
	}-*/;
	
	public void redirect(String url) {
		url = Window.Location.getPath().replaceAll("/[^/]*$", "/" + url);
		Window.Location.assign((isDevMode()? patchHref(url): url));
	}
	
	public GridField initCombobox(String valueFieldMap, String codeFieldMap, String allValue,
			ComboBox<ModelData> comboBox, String recordName, String... restUrl) {
		GridDescriptor descriptor = new GridDescriptor(recordName, restUrl);
		GridField nameField = descriptor.addTextField(valueFieldMap, (Element)null);
		GridField codeField = descriptor.addTextField(codeFieldMap, (Element)null);
		comboBox.setStore(createStore(descriptor, createModelDataAll(allValue, nameField)));
		comboBox.setDisplayField(nameField.getName());
		comboBox.setValueField(codeField.getName());
		return codeField;
	}

	private ModelData createModelDataAll(String allValue, GridField nameField) {
		if (allValue == null) {
			return null;
		}
		BaseModelData modelData = new BaseModelData();
		nameField.setValue(modelData, allValue);
		return modelData;
	}

	public void setUrfcApp(App urfcApp) {
		this.urfcApp = urfcApp;		
	}
	
	protected void addGooglet(BaseGooglet googlet) {
		urfcApp.addGooglet(getEventsDispatcher(), getName(), googlet);
	}

	protected void patchHyperlinks(Element element) {
		if (isDevMode()) {
			final NodeList<Element> nodeList = element.getElementsByTagName("a");
			final int length = nodeList.getLength();
			for (int i = 0; i < length; i++) {
				final AnchorElement anchorElement = AnchorElement.as(nodeList.getItem(i));
				anchorElement.setHref(patchHref(anchorElement.getHref()));
			}
		}
	}

}
